package com.example.jimuyutabletcontrol.activity;

import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.CircleOptions;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.Polyline;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.CoordinateConverter;
import com.baidu.mapapi.utils.DistanceUtil;
import com.example.jimuyutabletcontrol.FileActivity;
import com.example.jimuyutabletcontrol.R;
import com.example.jimuyutabletcontrol.bean.MakeTaskMapLine;
import com.example.jimuyutabletcontrol.bean.MakeTaskMapPoint;
import com.example.jimuyutabletcontrol.dialog.BaiduPathInfoDialogFragment;
import com.example.jimuyutabletcontrol.dialog.InputFileSelectDialog;
import com.example.jimuyutabletcontrol.dialog.InputLongitudeAndLatitudeDialogFragment;
import com.example.jimuyutabletcontrol.dialog.MakeTaskMapDialogFragment;
import com.example.jimuyutabletcontrol.dialog.OtherTaskSettingDialogFragment;
import com.example.jimuyutabletcontrol.dialog.TaskProjectSettingDialogFragment;
import com.example.jimuyutabletcontrol.location.LocationProvider;
import com.example.jimuyutabletcontrol.utils.Constants;
import com.example.jimuyutabletcontrol.utils.CoordinateTransformUtil;
import com.example.jimuyutabletcontrol.utils.DecimalFormatUtil;
import com.example.jimuyutabletcontrol.utils.MapUtil;
import com.example.jimuyutabletcontrol.utils.MeasuringDistancePointHelp;
import com.example.jimuyutabletcontrol.utils.TaskUtil;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.gson.Gson;
import com.marcoscg.headerdialog.HeaderDialog;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

public class MakeTaskMapActivity extends AppCompatActivity implements View.OnClickListener {

    private final int linePriority = 2;

    private final int pointPriority = 3;

    private final int[] markerImageResList = {
            R.drawable.taskmap_icon_marka, R.drawable.taskmap_icon_markb,
            R.drawable.taskmap_icon_markc, R.drawable.taskmap_icon_markd,
            R.drawable.taskmap_icon_marke, R.drawable.taskmap_icon_markf,
            R.drawable.taskmap_icon_markg, R.drawable.taskmap_icon_markh,
            R.drawable.taskmap_icon_marki, R.drawable.taskmap_icon_markj
    };

    private final String[] markerTextList = {
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J"
    };

    private MapView mapView;

    private BaiduMap baiduMap;

    public static LocationClient mLocationClient;

    public BDLocationListener myLocationListener = new MyLocationListener();
    private LatLng latLng;
    private boolean isFirstLoc = true; // 是否首次定位

    private Point[] pentagonVertices;

    private FloatingActionButton fabTools;

    private FloatingActionButton fabSend;

    private Button[] buttonsTools;

    private Button[] buttonsSend;

    private int startPositionX;

    private int startPositionY;

    private int toolsWhichAnimation;

    private int sendWhichAnimation;

    private int[] enterDelay = {0, 40, 80, 120, 160, 200, 240};

    private int[] exitDelay = {0, 40, 80, 120, 160, 200, 240};

    private Boolean isFabToolsClicked = false;

    private Boolean isFabSendClicked = false;

    private View mIconView;

    private TextView totalJourney;

    private TextView measureDistance;

    private TextView totalTime;

    private List<MakeTaskMapPoint> points;

    private List<MakeTaskMapLine> lines;

    private MeasuringDistancePointHelp distancePointHelp;

    private BDLocation currentLocation;

    private Timer timer;

    private TimerTask task;

    private LatLng currentlatLng;

    private View mView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.maketaskmapinterface_activity);
        SDKInitializer.initialize(getApplicationContext());
        initView();
        setBaseMapConf();
        setLocationRegister();
        setClickListener();
        prepareFloatButton();
        initData();
    }

    /**
     * 初始化数据
     */
    private void initData() {
        points = new ArrayList<>();
        lines = new ArrayList<>();
    }

    /**
     * 初始化view
     */
    private void initView() {
        mapView = findViewById(R.id.bmapViewmaketaskmap);
        baiduMap = mapView.getMap();
        totalJourney = findViewById(R.id.totalJourney);
        measureDistance = findViewById(R.id.measureDistance);
        totalTime = findViewById(R.id.totalTime);
    }

    private void setTotalTime() {
        totalTime.setText("总时间:" + DecimalFormatUtil.getFormatData(MapUtil.getTotalTime2(points)) + "分");
    }

    /**
     * 设置监听事件
     */
    private void setClickListener() {
        distancePointHelp = new MeasuringDistancePointHelp(this, baiduMap, 1);
        distancePointHelp.setOnMeasuringDistanceListener((isALLShow, distance) -> {
            measureDistance.setVisibility(isALLShow ? View.VISIBLE : View.GONE);
            if (isALLShow) {
                measureDistance.setText("测距距离:" + distance + "米");
            }
        });
        baiduMap.setOnMapLongClickListener(this::addPointToMap);
        baiduMap.setOnPolylineClickListener(polyline -> {
            MakeTaskMapLine line = getLineWithPolyline(polyline);
            if (null == line) return false;
            BaiduPathInfoDialogFragment dialogFragment =
                    BaiduPathInfoDialogFragment.getInstance(line.firstPoint.text
                            , line.secondPoint.text, line.firstPoint.selfPosition, line.secondPoint.selfPosition
                            , line.getDistance2(), line.getSpeed(), line.getNeedTimeMinute(), line.firstPoint.powerDepth);
            dialogFragment.show(getSupportFragmentManager(), "baiduPathInfoDialogFragment");
            return true;
        });
        baiduMap.setOnMarkerClickListener(marker -> {
            MakeTaskMapPoint point = getPointWithMark(marker);
            if (null == point) return false;
            MakeTaskMapPoint.PackageAuxiliaryPoint packageAuxiliaryPoint = point.getAuxiliaryPoint();
            if (null == packageAuxiliaryPoint) return false;
            if (null == currentlatLng)return false;
            LatLng currentLatlng = CoordinateTransformUtil.baiduToGps(currentlatLng);
            TaskProjectSettingDialogFragment dialog = TaskProjectSettingDialogFragment.getInstance(packageAuxiliaryPoint,currentLatlng);
            dialog.setOnTaskProjectSettingDialogListener(aPoint -> {
                point.depthLimit = aPoint.auxiliaryPoint.depthLimit;
                point.isGpsAdjusting = aPoint.auxiliaryPoint.isGpsAdjusting;
                point.powerDepth = aPoint.auxiliaryPoint.powerDepth;
                point.powerSpeed = aPoint.auxiliaryPoint.powerSpeed;
                LatLng latLng = CoordinateTransformUtil.gpsToBaidu(new LatLng(aPoint.auxiliaryPoint.latitude, aPoint.auxiliaryPoint.longitude));
                LatLng selfPosition = point.selfPosition;
                if (selfPosition.longitude != latLng.longitude || selfPosition.latitude != latLng.latitude) {
                    refreshPoint(latLng, point);
                    refreshLines();
                }
                Toast.makeText(MakeTaskMapActivity.this, "设置成功", Toast.LENGTH_SHORT).show();
            });
            dialog.show(getSupportFragmentManager(), "TaskProjectSettingDialogFragment");
            return true;
        });
    }

    private void setBaseMapConf() {
        baiduMap.clear();
        MapStatus.Builder builder = new MapStatus.Builder();
        builder.zoom(4.0f);
        baiduMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
    }

    //配置定位SDK参数
    public static void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy
        );//可选，默认高精度，设置定位模式，高精度，低功耗，仅设备
        option.setCoorType("bd09ll");//可选，默认gcj02，设置返回的定位结果坐标系
        int span = 1000;
        option.setScanSpan(span);//可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(true);//可选，设置是否需要地址信息，默认不需要
        option.setOpenGps(true);//可选，默认false,设置是否使用gps
        option.setLocationNotify(true);//可选，默认false，设置是否当GPS有效时按照1S/1次频率输出GPS结果
        option.setIsNeedLocationDescribe(true);//可选，默认false，设置是否需要位置语义化结果，可以在BDLocation
        // .getLocationDescribe里得到，结果类似于“在北京天安门附近”
        option.setIsNeedLocationPoiList(true);//可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
        option.setIgnoreKillProcess(false);
        option.setOpenGps(true); // 打开gps

        //可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认不杀死
        option.SetIgnoreCacheException(false);//可选，默认false，设置是否收集CRASH信息，默认收集
        option.setEnableSimulateGps(false);//可选，默认false，设置是否需要过滤GPS仿真结果，默认需要
        mLocationClient.setLocOption(option);
    }

    private void setLocationRegister() {
        //获取地图控件引用
        baiduMap = mapView.getMap();
        //普通地图
        baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        baiduMap.setMyLocationEnabled(true);

        //默认显示普通地图
        baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        //开启交通图
        //mBaiduMap.setTrafficEnabled(true);
        //开启热力图
        //mBaiduMap.setBaiduHeatMapEnabled(true);
        // 开启定位图层
        baiduMap.setMyLocationEnabled(true);
        mLocationClient = new LocationClient(getApplicationContext());     //声明LocationClient类
        //配置定位SDK参数
        initLocation();
        mLocationClient.registerLocationListener(myLocationListener);    //注册监听函数
        //开启定位
        mLocationClient.start();
        //图片点击事件，回到定位点
        mLocationClient.requestLocation();
    }

    //实现BDLocationListener接口,BDLocationListener为结果监听接口，异步获取定位结果
    public class MyLocationListener implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {
            latLng = new LatLng(location.getLatitude(), location.getLongitude());
            // 构造定位数据
            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    // 此处设置开发者获取到的方向信息，顺时针0-360
                    .direction(100).latitude(location.getLatitude())
                    .longitude(location.getLongitude()).build();
            // 设置定位数据
            baiduMap.setMyLocationData(locData);
            // 当不需要定位图层时关闭定位图层
            //mBaiduMap.setMyLocationEnabled(false);
            if (isFirstLoc) {
                isFirstLoc = false;
                LatLng ll = new LatLng(location.getLatitude(),
                        location.getLongitude());
                MapStatus.Builder builder = new MapStatus.Builder();
                builder.target(ll).zoom(18.0f);
                baiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));

                if (location.getLocType() == BDLocation.TypeGpsLocation) {
                    // GPS定位结果
                    Toast.makeText(MakeTaskMapActivity.this, location.getAddrStr(), Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
                    // 网络定位结果
                    Toast.makeText(MakeTaskMapActivity.this, location.getAddrStr(), Toast.LENGTH_SHORT).show();

                } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {
                    // 离线定位结果
                    Toast.makeText(MakeTaskMapActivity.this, location.getAddrStr(), Toast.LENGTH_SHORT).show();

                } else if (location.getLocType() == BDLocation.TypeServerError) {
                    Toast.makeText(MakeTaskMapActivity.this, "服务器错误，请检查", Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                    Toast.makeText(MakeTaskMapActivity.this, "网络错误，请检查", Toast.LENGTH_SHORT).show();
                } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                    Toast.makeText(MakeTaskMapActivity.this, "手机模式错误，请检查是否飞行", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (null != mapView) {
            mapView.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (null != mapView) {
            mapView.onResume();
        }
    }

    /**
     * 改变marker经纬度，并移动到指定位置
     *
     * @param baiduPoint
     * @param makeTaskMapPoint
     */
    private void refreshPoint(LatLng baiduPoint, MakeTaskMapPoint makeTaskMapPoint) {
        if (makeTaskMapPoint.overlay instanceof Marker) {
            makeTaskMapPoint.selfPosition = baiduPoint;
            Marker marker = (Marker) makeTaskMapPoint.overlay;
            marker.setPosition(makeTaskMapPoint.selfPosition);
        }
    }

    /**
     * marker经纬度与位置的改变，将连接的线改变
     */
    private void refreshLines() {
        for (MakeTaskMapLine line : lines) {
            if (line.isResetLine()) {
                line.resetLine();
            }
        }
        setTotalJourney();
    }

    /**
     * 设置总航程
     */
    public void setTotalJourney() {
        double distance = 0;
        for (MakeTaskMapLine line : lines) {
            distance += line.getDistance2();
        }
        totalJourney.setText("总航程:" + ((int) distance) + "米");
    }

    /**
     * 添加marker与line到map里
     *
     * @param latLng
     */
    private void addPointToMap(LatLng latLng) {
        if (null != currentLocation){
            double dis = DistanceUtil.getDistance(currentlatLng, latLng);
            if (dis>10*1000){
                Toast.makeText(this,"只能设置周边10km范围",Toast.LENGTH_SHORT).show();
                return;
            }
        }
        MakeTaskMapPoint point = new MakeTaskMapPoint();
        point.position = points.size();
        point.selfPosition = latLng;
        point.text = (point.position+1)+"";
        point.bitmapDescriptor = measuringDistanceDrawble(point.text);
        point.overlayOptions = point.getPointOverlayOptions(pointPriority);
        point.overlay = baiduMap.addOverlay(point.overlayOptions);
        points.add(point);
        setTotalTime();
        if (points.size() > 1) {
            MakeTaskMapLine line = new MakeTaskMapLine();
            line.firstPoint = points.get(points.size() - 2);
            line.secondPoint = points.get(points.size() - 1);
            line.overlayOptions = line.getLineOverlayOptions(linePriority);
            line.mPolyline = baiduMap.addOverlay(line.overlayOptions);
            lines.add(line);
            setTotalJourney();
        }
    }

    /**
     * 添加marker与line到map里
     *
     * @param packageAuxiliaryPoint
     */
    private void addPointToMap(MakeTaskMapPoint.PackageAuxiliaryPoint packageAuxiliaryPoint) {
        MakeTaskMapPoint mapPoint = MakeTaskMapPoint.createMapPoint(packageAuxiliaryPoint);
        mapPoint.position = points.size();
        mapPoint.bitmapDescriptor = measuringDistanceDrawble(mapPoint.text);
        mapPoint.overlayOptions = mapPoint.getPointOverlayOptions(pointPriority);
        mapPoint.overlay = baiduMap.addOverlay(mapPoint.overlayOptions);
        points.add(mapPoint);
        setTotalTime();
        if (points.size() > 1) {
            MakeTaskMapLine line = new MakeTaskMapLine();
            line.firstPoint = points.get(points.size() - 2);
            line.secondPoint = points.get(points.size() - 1);
            line.overlayOptions = line.getLineOverlayOptions(linePriority);
            line.mPolyline = baiduMap.addOverlay(line.overlayOptions);
            lines.add(line);
            setTotalJourney();
        }
    }

    /**
     * 通过经纬度来设置航线点
     */
    private void createHeaderAddGPSDialog() {
        new HeaderDialog(this).setColor(getResources().getColor(R.color.Control3)) // Sets the header background color
                .setElevation(false) // Sets the header elevation, true by default
                .setIcon(getResources().getDrawable(R.drawable.ic_content_paste_black_24dp)) // Sets the dialog icon image
                .setTitle(getResources().getString(R.string.addparameter)) // Sets the dialog title
                .setMessage("请在下面添加任务" + markerImageResList[points.size()] + "点的GPS数据") // Sets the dialog message
                .justifyContent(true) // Justifies the message text, false by default
                .setTitleColor(Color.parseColor("#212121")) // Sets the header title text color
                .setIconColor(Color.parseColor("#212121")) // Sets the header icon color
                .setTitleGravity(Gravity.CENTER_HORIZONTAL) // Sets the header title text gravity
                .setMessageGravity(Gravity.CENTER_HORIZONTAL) // Sets the message text gravity
                .setTitleMultiline(false) // Multiline header title text option, true by default
                .setView(R.layout.maketaskmapaddgps_dialog) // Set custom view to the dialog (only possible via layout resource)
                .setPositiveButton("确定", (dialog, which) -> {
                    if (dialog instanceof AlertDialog) {
                        Window window = ((AlertDialog) dialog).getWindow();
                        if (null != window) {
                            View view = window.getDecorView();
                            EditText editLatitude = view.findViewById(R.id.taskmapeditlatitude);
                            EditText editLongtitude = view.findViewById(R.id.taskmapeditlongtitude);
                            String value1 = editLatitude.getText().toString().trim();
                            String value2 = editLongtitude.getText().toString().trim();
                            if (TextUtils.isEmpty(value1) || TextUtils.isEmpty(value2)) {
                                toastMsg("请输入经纬度");
                            } else {
                                double latitude = Double.valueOf(value1);
                                double longtitude = Double.valueOf(value2);
                                if (latitude > 90 || latitude < -90 || longtitude > 180 || longtitude < -180) {
                                    toastMsg("请输入正确的经纬度");
                                } else {
                                    LatLng point = new LatLng(latitude, longtitude);
                                    addPointToMap(CoordinateTransformUtil.gpsToBaidu(point));
                                }
                            }
                        }
                    }
                })
                .setNegativeButton("取消", (dialog, which) -> {
                }).create().show();
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK) return;
        switch (requestCode) {
            case 200:
                if (null != data) {
                    String path = data.getStringExtra(FileActivity.KEY_RESULT_DATA);
                    if (!TextUtils.isEmpty(path)) {
                        List<MakeTaskMapPoint.PackageAuxiliaryPoint> list = TaskUtil.getTaskWithTaskFile(path);
                        for (MakeTaskMapPoint.PackageAuxiliaryPoint auxiliaryPoint : list) {
                            addPointToMap(auxiliaryPoint);
                        }
                    }
                }
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != distancePointHelp) {
            distancePointHelp.onDestroy();
            distancePointHelp = null;
        }
        if (null != mLocationClient) {
            mLocationClient.unRegisterLocationListener(myLocationListener);
            mLocationClient.stop();
            mLocationClient = null;
        }
        if (null != baiduMap) {
            baiduMap.setMyLocationEnabled(false);
            baiduMap = null;
        }
        if (null != mapView) {
            mapView.onDestroy();
            mapView = null;
        }
        if (null != points) {
            for (MakeTaskMapPoint point : points) {
                point.recycle();
            }
            points.clear();
            points = null;
        }
        if (null != lines) {
            for (MakeTaskMapLine line : lines) {
                line.recycle();
            }
            lines.clear();
            lines = null;
        }
        mIconView = null;
        if (null != timer) {
            timer.cancel();
            timer = null;
        }
        if (null != task) {
            task.cancel();
            task = null;
        }
    }

    @Override
    public void onClick(View view) {
        boolean isToolsSubClicked = false;
        boolean isSendSubClicked = false;
        switch (view.getId()) {
            case R.id.fabmaketasktool:
                isToolsSubClicked = true;
                isSendSubClicked = true;
                if (!isFabSendClicked) {
                    isFabToolsClicked = true;
                    if (toolsWhichAnimation == 0) {
                        /**
                         * Getting the center point of floating action button
                         *  to set start point of buttons
                         */
                        startPositionX = 2600;
                        startPositionY = 0;
                        for (Button button : buttonsTools) {
                            button.setX(startPositionX);
                            button.setY(startPositionY);
                            button.setVisibility(View.VISIBLE);
                        }
                        for (int i = 0; i < buttonsTools.length; i++) {
                            playEnterAnimation(buttonsTools[i], i);
                        }
                        toolsWhichAnimation = 1;
                    } else {
                        for (int i = 0; i < buttonsTools.length; i++) {
                            playExitAnimation(buttonsTools[i], i);
                        }
                        toolsWhichAnimation = 0;
                        isFabToolsClicked = false;
                    }
                }
                break;
            case R.id.fabmaketasksend:
                isSendSubClicked = true;
                isToolsSubClicked = true;
                if (!isFabToolsClicked) {
                    isFabSendClicked = true;
                    if (sendWhichAnimation == 0) {
                        /**
                         * Getting the center point of floating action button
                         *  to set start point of buttons
                         */
                        startPositionX = 2600;
                        startPositionY = 0;
                        for (Button button : buttonsSend) {
                            button.setX(startPositionX);
                            button.setY(startPositionY);
                            button.setVisibility(View.VISIBLE);
                        }
                        for (int i = 0; i < buttonsSend.length; i++) {
                            playEnterAnimation(buttonsSend[i], i);
                        }
                        sendWhichAnimation = 1;
                    } else {
                        for (int i = 0; i < buttonsSend.length; i++) {
                            playExitAnimation(buttonsSend[i], i);
                        }
                        sendWhichAnimation = 0;
                        isFabSendClicked = false;
                    }
                }
                break;
        }

        if (isFabToolsClicked && !isToolsSubClicked) {
            switch ((int) view.getTag()) {
                case 0:
                    realTimeLocation();
                    break;
                case 1:
                    createHeaderAddGPSDialog();
                    break;
                case 2:
                    removeLastPoint();
                    break;
                case 3:
                    removeAll();
                    break;
                case 4:
                    dataSave();
                    break;
            }
        }
        if (isFabSendClicked && !isSendSubClicked) {
            switch ((int) view.getTag()) {
                case 0:
                    onClick(fabSend);
                    InputFileSelectDialog selectDialog = new InputFileSelectDialog();
                    selectDialog.setOnInputFileSelectListener(() -> {
                        if (null != points && points.size() > 0) {
                            toastMsg("数据未保存");
                            return;
                        }
                        Intent fileIntent = new Intent();
                        fileIntent.setClass(MakeTaskMapActivity.this, FileActivity.class);
                        fileIntent.putExtra(FileActivity.KEY_FILE_PATH, Constants.FILE_PATH + Constants.TASKMAPFOLDER);
                        ArrayList<String> list = new ArrayList<>();
                        list.add(Constants.TASK_SIGN);
                        fileIntent.putExtra(FileActivity.KEY_LIMIT, list);
                        startActivityForResult(fileIntent, 200);
                    });
                    selectDialog.show(getSupportFragmentManager(), "InputFileSelectDialog");
                    break;
                case 1:
                    onClick(fabSend);
                    Intent intent = new Intent(MakeTaskMapActivity.this, MappingActivity.class);
                    startActivity(intent);
                    break;
            }
        }
    }

    /**
     * 数据保存点击事件
     */
    private void dataSave() {
        int length = points.size();
        if (length >= 1) {
            List<MakeTaskMapPoint.PackageAuxiliaryPoint> auxiliaryPoints = new ArrayList<>();
            for (MakeTaskMapPoint point : points) {
                auxiliaryPoints.add(point.getAuxiliaryPoint());
            }
            String content = new Gson().toJson(auxiliaryPoints);
            TaskUtil.saveTask(content);
            removeAll();
            toastMsg("数据保存完毕");
        } else {
            toastMsg("无数据需要保存");
        }
    }

    /**
     * 实时定位点击事件
     */
    private void realTimeLocation() {
        if (null != baiduMap && !baiduMap.isMyLocationEnabled()) {
            baiduMap.setMyLocationEnabled(true);
        }
        if (null != mLocationClient && !mLocationClient.isStarted()) {
            mLocationClient.start();
        }
    }

    /**
     * 删除末点点击事件
     */
    private void removeLastPoint() {
        if (null != points && points.size() > 0) {
            MakeTaskMapPoint point = points.get(points.size() - 1);
            removePointData(point);
            points.remove(point);
            setTotalTime();
        }
        if (lines.size() > 0) {
            MakeTaskMapLine line = lines.get(lines.size() - 1);
            removeLineData(line);
            lines.remove(line);
            setTotalJourney();
        }
    }

    /**
     * 全部删除按钮点击事件
     */
    private void removeAll() {
        removeAllLineData();
        removeAllPointData();
        setTotalJourney();
        setTotalTime();
    }

    public MakeTaskMapLine getLineWithPolyline(Polyline polyline) {
        if (null == polyline) return null;
        for (MakeTaskMapLine line : lines) {
            if (null != line.mPolyline && line.mPolyline == polyline) {
                return line;
            }
        }
        return null;
    }

    public MakeTaskMapPoint getPointWithMark(Marker marker) {
        if (null == marker) return null;
        for (MakeTaskMapPoint point : points) {
            if (point.overlay == marker) {
                return point;
            }
        }
        return null;
    }


    private void removeAllPointData() {
        for (MakeTaskMapPoint point : points) {
            removePointData(point);
        }
        points.clear();
    }

    private void removeAllLineData() {
        for (MakeTaskMapLine line : lines) {
            removeLineData(line);
        }
        lines.clear();
    }

    private void removePointData(MakeTaskMapPoint point) {
        if (null != point.overlay && !point.overlay.isRemoved()) {
            point.overlay.remove();
            point.overlay = null;
        }
        point.overlayOptions = null;
        point.text = null;
        point.selfPosition = null;
        if (null != point.bitmapDescriptor) {
            point.bitmapDescriptor.recycle();
        }
    }

    private void removeLineData(MakeTaskMapLine line) {
        if (null != line.mPolyline && !line.mPolyline.isRemoved()) {
            line.mPolyline.remove();
            line.mPolyline = null;
        }
        line.secondPoint = null;
        line.firstPoint = null;
        line.overlayOptions = null;
    }

    private void toastMsg(final String msg) {
        runOnUiThread(() -> Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show());
    }


    private BitmapDescriptor measuringDistanceDrawble(String text) {
        if (null == mView) {
            mView = LayoutInflater.from(this).inflate(R.layout.make_map_shipe_item, null);
        }
        TextView tv = mView.findViewById(R.id.tv);
        if (!TextUtils.isEmpty(text)) {
            tv.setText(text);
        }
        mView.setDrawingCacheEnabled(true);
        mView.measure(
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        mView.layout(0, 0,
                mView.getMeasuredWidth(),
                mView.getMeasuredHeight());
        mView.buildDrawingCache();
        //获取到图片，这样就可以添加到Map上
        return BitmapDescriptorFactory.fromView(mView);
    }


    private void prepareFloatButton() {
        startPositionX = 0;
        startPositionY = 0;
        toolsWhichAnimation = 0;
        fabTools = findViewById(R.id.fabmaketasktool);
        fabSend = findViewById(R.id.fabmaketasksend);
        fabTools.setOnClickListener(this);
        fabSend.setOnClickListener(this);
        pentagonVertices = new Point[10];
        pentagonVertices[0] = new Point(10, 180);
        pentagonVertices[1] = new Point(10, 380);
        pentagonVertices[2] = new Point(10, 580);
        pentagonVertices[3] = new Point(10, 780);
        pentagonVertices[4] = new Point(10, 980);
        pentagonVertices[5] = new Point(10, 1180);
        String[] contentTools = {"实时定位", "添加新点", "删除末点", "全部删除", "保存数据"};
        String[] contentSend = {"修改任务"};
        buttonsTools = calculatePentagonVertices(contentTools.length, contentTools);
        buttonsSend = calculatePentagonVertices(contentSend.length, contentSend);
    }

    private Button[] calculatePentagonVertices(int number, String[] content) {
        Button[] buttons = new Button[number];
        for (int i = 0; i < buttons.length; i++) {
            buttons[i] = new Button(MakeTaskMapActivity.this);
            buttons[i].setLayoutParams(new RelativeLayout.LayoutParams(100, 100));
            buttons[i].setX(0);
            buttons[i].setY(0);
            buttons[i].setTag(i);
            buttons[i].setOnClickListener(this);
            buttons[i].setVisibility(View.INVISIBLE);
            buttons[i].setBackgroundResource(R.drawable.circular_background);
            buttons[i].setTextColor(Color.DKGRAY);
            buttons[i].setText(content[i]);
            buttons[i].setTextSize(14);
            ((LinearLayout) findViewById(R.id.maketaskmap_main)).addView(buttons[i]);
        }
        return buttons;
    }

    private void playEnterAnimation(final Button button, int position) {
        /**
         * Animator that animates buttons x and y position simultaneously with size
         */
        AnimatorSet buttonAnimator = new AnimatorSet();

        /**
         * ValueAnimator to update x position of a button
         */
        ValueAnimator buttonAnimatorX = ValueAnimator.ofFloat(startPositionX,
                pentagonVertices[position].x);
        buttonAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setX((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorX.setDuration(300);

        /**
         * ValueAnimator to update y position of a button
         */
        ValueAnimator buttonAnimatorY = ValueAnimator.ofFloat(startPositionY,
                pentagonVertices[position].y);
        buttonAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setY((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorY.setDuration(300);

        /**
         * This will increase the size of button
         */
        ValueAnimator buttonSizeAnimator = ValueAnimator.ofInt(6, 170);
        buttonSizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.getLayoutParams().width = (int) animation.getAnimatedValue();
                button.getLayoutParams().height = (int) animation.getAnimatedValue();
                button.requestLayout();
            }
        });
        buttonSizeAnimator.setDuration(300);

        /**
         * Add both x and y position update animation in
         *  animator set
         */
        buttonAnimator.play(buttonAnimatorX).with(buttonAnimatorY).with(buttonSizeAnimator);
        buttonAnimator.setStartDelay(enterDelay[position]);
        buttonAnimator.start();
    }

    private void playExitAnimation(final Button button, int position) {

        /**
         * Animator that animates buttons x and y position simultaneously with size
         */
        AnimatorSet buttonAnimator = new AnimatorSet();

        /**
         * ValueAnimator to update x position of a button
         */
        ValueAnimator buttonAnimatorX = ValueAnimator.ofFloat(pentagonVertices[position].x,
                startPositionX);
        buttonAnimatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setX((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorX.setDuration(300);

        /**
         * ValueAnimator to update y position of a button
         */
        ValueAnimator buttonAnimatorY = ValueAnimator.ofFloat(pentagonVertices[position].y,
                startPositionY);
        buttonAnimatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.setY((float) animation.getAnimatedValue());
                button.requestLayout();
            }
        });
        buttonAnimatorY.setDuration(300);

        /**
         * This will decrease the size of button
         */
        ValueAnimator buttonSizeAnimator = ValueAnimator.ofInt(170, 6);
        buttonSizeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                button.getLayoutParams().width = (int) animation.getAnimatedValue();
                button.getLayoutParams().height = (int) animation.getAnimatedValue();
                button.requestLayout();
            }
        });
        buttonSizeAnimator.setDuration(300);

        /**
         * Add both x and y position update animation in
         *  animator set
         */
        buttonAnimator.play(buttonAnimatorX).with(buttonAnimatorY).with(buttonSizeAnimator);
        buttonAnimator.setStartDelay(exitDelay[position]);
        buttonAnimator.start();
    }
}
